# -*- coding: utf-8 -*-
"""
Created on Mon Jan 22 09:52:59 2018

@author: Matt
"""

from numpy import *
import operator  # 进行排序
import matplotlib.pyplot as plt


def createDataSet():
    group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]])
    labels = ['A', 'A', 'B', 'B']
    return group, labels


# 2.1.2 k-近邻算法 分类器
# classify0 有四个输入参数：用于分类的输入向量inX ， 输入的训练样本集dataSet
#       标签向量为labels，选择最近邻居数目K
def classify0(inX, dataSet, labels, K):
    dataSetSize = dataSet.shape[0]  # shape返回dataSet的行列信息 此处为4*2 0号位置为4
    # 距离计算
    #  tile(A,reps) 重复A的reps个维度 详见函数定义
    #  inX扩充后得到diffMat 重复dataSetSize次
    diffMat = tile(inX, (dataSetSize, 1)) - dataSet
    # 差取平方后求和开根号 完成距离计算
    sqDiffMat = diffMat ** 2
    sqDistances = sqDiffMat.sum(axis=1)  # axis=1表示按行相加，axis=0表示按列相加
    distances = sqDistances ** 0.5
    sortedDistIndicies = distances.argsort()  # argsort是排序，将元素按照由小到大的顺序返回下标，比如([2,1,4]),它返回的就是([1,0,2])
    classCount = {}
    for i in range(K):
        voteIlabel = labels[sortedDistIndicies[i]]  # 选择前k个元素对应的标签
        # get为取字典里的元素 如果之前这个voteIlabel存在字典中 那么就返回字典里这个voteIlabel里的值，如果没有就返回default值 此处为0
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
    # 对classCount进行排序 按照1号位置的元素大学逆序输出
    sortedClassCount = sorted(classCount.items(),
                              key=operator.itemgetter(1), reverse=True)
    # 返回最近的一个
    return sortedClassCount[0][0]


# Test one
# group,labels=createDataSet()
# 以上述四个坐标为训练集，取前3个labels，判断[0,0]位置的属性
# print(classify0([0,0],group,labels,3))

# 2.2 为海仑改进约会网站配对效果
# 将文本记录到转换Numpy的解析程序
# 飞行里程、游戏时间、冰淇淋
def file2matrix(filename):  # 读入‘datingTestSet2.txt’
    fr = open(filename)
    arrayOLines = fr.readlines()
    numberOfLines = len(arrayOLines)  # 得到文本行数
    returnMat = zeros((numberOfLines, 3))  # 创建以0填充的Numpy矩阵，另一维度固定为3
    classLabelVector = []
    index = 0
    # 解析文件数据到列表
    for line in arrayOLines:
        line = line.strip()  # 移除字符串头尾指定的字符 截取所有回车字符
        listFromLine = line.split('\t')  # 原始值含\t 使用tab将整行数据分割为元素列表
        returnMat[index, :] = listFromLine[0:3]  # 取listFromLine的前3个元素放入returnMat矩阵的index行 逗号后面意思是有多少放多少
        classLabelVector.append(int(listFromLine[-1]))  # 取listFromLine最后一个元素(分类结果 即标签)放入LabelVec
        index += 1
    return returnMat, classLabelVector


# Test Two  绘制散点图
datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
fig = plt.figure()
ax = fig.add_subplot(111)  # 1行1列第一幅图
ax.set_title('videoGame & icecream')
ax.set_xlabel('videoGame')
ax.set_ylabel('icecream')
# ax.scatter(datingDataMat[:,1],datingDataMat[:,2])
# 对比以下两幅图能发现更好的分类方法
ax.scatter(datingDataMat[:, 1], datingDataMat[:, 2], 15.0 * array(datingLabels), 15.0 * array(datingLabels))
# ax.scatter(datingDataMat[:, 0], datingDataMat[:, 1], 15.0 * array(datingLabels), 15.0 * array(datingLabels))
# plt.show()


# 分析数据：使用Matplotlib创建散点图
# 数据归一化
def autoNorm(dataSet):
    # 获取每列！最大最小值
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = zeros(shape(dataSet))  # 创建形如dataSet的零矩阵
    m = dataSet.shape[0]  # 行数
    normDataSet = dataSet - tile(minVals, (m, 1))
    normDataSet = normDataSet / tile(ranges, (m, 1)) # 注意此处除法是对于矩阵而言的
    return normDataSet, ranges, minVals


# 分类器的测试代码
def datingClassTest():
    hoRatio = 0.1 # 测试数据比例
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    normMat, ranges, minVals = autoNorm(datingDataMat)
    m = normMat.shape[0]
    numTestVecs = int(m * hoRatio)
    errorCount = 0.0
    for i in range(numTestVecs):
        # 把后90%发送给分类器进行分类
        classifierResult = classify0(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 3)
        print('the classifier came back with: %d,the real answer is : %d' % (classifierResult, datingLabels[i]))
        if (classifierResult != datingLabels[i]):
            errorCount += 1.0
    print("the total error rate is :%f %% " % float((errorCount / float(numTestVecs)) * 100))


# Test Three
# datingClassTest()

# 构建完整可用系统
def classifyPerson():
    resultList = ['not at all', 'in small doses', 'in large doses']
    percentTats = float(input("percentange of time spent playing video games?"))
    ffMiles = float(input(
        'frequent flier miles earned per year?'))
    iceCream = float(input(
        'liters of ice cream consumed per year?'))
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    normMat, ranges, minVals = autoNorm(datingDataMat)
    inArr = array([ffMiles, percentTats, iceCream])
    classifierResult = classify0((inArr - minVals) / ranges, normMat, datingLabels, 3)
    print('You will probably like this person', resultList[classifierResult - 1])

# Test Four
# classifyPerson()
